package com.yanqu.road.server.gameplayer.module.activity.curio;

import com.alibaba.fastjson.JSONObject;
import com.mysql.jdbc.log.LogUtils;
import com.yanqu.road.dao.impl.curio.UserCurioCountDataDaoImpl;
import com.yanqu.road.dao.impl.curio.UserCurioDataDaoImpl;
import com.yanqu.road.dao.impl.curio.UserCurioItemDataDaoImpl;
import com.yanqu.road.dao.impl.curio.UserCurioSkillDataDaoImpl;
import com.yanqu.road.entity.activity.args.ValueFourParamArgs;
import com.yanqu.road.entity.config.goods.GoodsInfo;
import com.yanqu.road.entity.config.skill.SkillInfo;
import com.yanqu.road.entity.config.skill.SkillUpgradeInfo;
import com.yanqu.road.entity.curio.*;
import com.yanqu.road.entity.curio.config.*;
import com.yanqu.road.entity.curio.enums.eCurioSkillType;
import com.yanqu.road.entity.enums.*;
import com.yanqu.road.entity.log.curio.*;
import com.yanqu.road.entity.player.UserBadge;
import com.yanqu.road.exception.BusinessException;
import com.yanqu.road.logic.config.GameConfig;
import com.yanqu.road.pb.cangbao.CurioProto;
import com.yanqu.road.pb.worldmessage.WorldMessageProto;
import com.yanqu.road.server.gameplayer.GamePlayer;
import com.yanqu.road.server.gameplayer.module.base.GeneralModule;
import com.yanqu.road.server.gameplayer.module.manor.ManorHarvestModel;
import com.yanqu.road.server.gameplayer.module.manor.ManorModule;
import com.yanqu.road.server.gameplayer.module.player.BadgeModule;
import com.yanqu.road.server.gameplayer.module.player.BagModule;
import com.yanqu.road.server.gameplayer.module.player.CurrencyModule;
import com.yanqu.road.server.gameplayer.module.player.EarnSpeedModule;
import com.yanqu.road.server.manger.activity.curio.CurioConfig;
import com.yanqu.road.server.manger.activity.curio.CurioConfigMgr;
import com.yanqu.road.server.manger.activity.curio.CurioMgr;
import com.yanqu.road.server.manger.config.GoodsMgr;
import com.yanqu.road.server.manger.config.SkillMgr;
import com.yanqu.road.server.manger.config.SystemOpenMgr;
import com.yanqu.road.server.manger.log.AutoLogMgr;
import com.yanqu.road.server.manger.player.WorldMessageMgr;
import com.yanqu.road.server.manger.rank.RankMgr;
import com.yanqu.road.server.pb.PlayerPb;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.config.Config;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;


import java.math.BigInteger;
import java.util.*;

public class CurioModule extends GeneralModule {

    /**
     * 玩家数据
     */
    private UserCurioData userCurioData;

    /**
     * 藏品
     */
    private Map<Integer, UserCurioItemData> curioItemDataMap;

    /**
     * 技能
     */
    private Map<Integer, UserCurioSkillData> skillDataMap;

    /**
     * 统计值
     */
    private Map<Integer, Map<Integer, UserCurioCountData>> countDataMap;

    public CurioModule(GamePlayer player) {
        super(player);
    }

    @Override
    public boolean loadData() {
        userCurioData = new UserCurioDataDaoImpl().getUserCurioData(player.getUserId());
        curioItemDataMap = new UserCurioItemDataDaoImpl().getUserCurioItemData(player.getUserId());
        skillDataMap = new UserCurioSkillDataDaoImpl().getUserCurioSkillData(player.getUserId());
        countDataMap = new UserCurioCountDataDaoImpl().getUserCurioCountData(player.getUserId());
        return true;
    }

    @Override
    public boolean afterLoadData() {

        //徽章数据特殊处理
        if(userCurioData != null && userCurioData.getBadgeLv() > 1){
            Map<Integer, List<UserBadge>> userBadgeMap = player.getModule(BadgeModule.class).getUserBadgeMap();
            if(userBadgeMap != null){
                synchronized (userBadgeMap){
                    List<UserBadge> curioBadges = userBadgeMap.get(eBadgeType.CurioScore.getValue());
                    CurioBadgeInfo badgeInfo = CurioConfigMgr.getConfig().getBadgeInfo(userCurioData.getBadgeLv());
                    if(curioBadges != null && badgeInfo != null){
                        //去掉重复的徽章
                        curioBadges.removeIf(next -> next.getBadgeId() < badgeInfo.getId());
                    }
                }
            }
        }

        //套装技能修复
        if(skillDataMap != null){
            UserCurioSkillData skillData = skillDataMap.get(705806);
            if(skillData != null && skillData.getLv() == 0 && skillData.getAddition() == 0){
                CurioItemSuitInfo suitInfo = CurioConfigMgr.getConfig().getCurioItemSuitInfo(7);
                if(suitInfo != null){
                    SkillInfo skillInfo = SkillMgr.getSkillInfo(705806);
                    if(skillInfo != null){
                        int lv = 0;
                        for (int i = 0; i < 10; i++) {
                            SkillUpgradeInfo upgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), lv);
                            long starNum = upgradeInfo.getConsumeCount();
                            if(starNum <= 0){
                                break;
                            }
                            boolean fill = true;
                            //全部星级要满足
                            for (int id : suitInfo.getCurioList()) {
                                if (!curioItemDataMap.containsKey(id)) {
                                    fill = false;
                                    break;
                                }
                                UserCurioItemData itemData = curioItemDataMap.get(id);
                                if (itemData.getStarLv() < starNum) {
                                    fill = false;
                                    break;
                                }
                            }
                            if(fill){
                                lv += 1;
                            }else {
                                break;
                            }
                        }
                        if(lv > 0){
                            skillData.setLv(lv);
                            CurioMgr.getLogger().error("修复玩家{}，套装效果705806 等级{}", player.getUserId(), lv);
                        }else {
                            CurioMgr.getLogger().error("修复玩家{}，套装效果705806 失败", player.getUserId());
                        }
                    }
                }
            }
        }

        return true;
    }

    @Override
    public boolean saveData() {
        if(userCurioData != null){
            if(userCurioData.isInsertOption()){
                new UserCurioDataDaoImpl().add(userCurioData);
            }else if(userCurioData.isUpdateOption()){
                new UserCurioDataDaoImpl().update(userCurioData);
            }
        }
        for (Map.Entry<Integer, UserCurioItemData> entry : curioItemDataMap.entrySet()) {
            UserCurioItemData itemData = entry.getValue();
            if(itemData.isInsertOption()){
                new UserCurioItemDataDaoImpl().add(itemData);
            }else if(itemData.isUpdateOption()){
                new UserCurioItemDataDaoImpl().update(itemData);
            }
        }
        for (Map.Entry<Integer, UserCurioSkillData> dataEntry : skillDataMap.entrySet()) {
            UserCurioSkillData skillData = dataEntry.getValue();
            if(skillData.isInsertOption()){
                new UserCurioSkillDataDaoImpl().add(skillData);
            }else if(skillData.isUpdateOption()){
                new UserCurioSkillDataDaoImpl().update(skillData);
            }
        }

        for (Map.Entry<Integer, Map<Integer, UserCurioCountData>> entry : countDataMap.entrySet()) {
            for (Map.Entry<Integer, UserCurioCountData> dataEntry : entry.getValue().entrySet()) {
                UserCurioCountData countData = dataEntry.getValue();
                if(countData.isInsertOption()){
                    new UserCurioCountDataDaoImpl().add(countData);
                }else if(countData.isUpdateOption()){
                    new UserCurioCountDataDaoImpl().update(countData);
                }
            }
        }
        return true;
    }

    @Override
    public void loginSendMsg() {
        if(isSystemOpen()){
            initUserData();
            checkAllCurioItemSpecialSkill();
            checkPrivilegeExpire();
            CurioMgr.calAllSkillAddition(player);
            syncUserData();
        }
    }

    @Override
    public void afterLogin() {
        for (Map.Entry<Integer, BigInteger> entry : CurioMgr.getGroupCurioMaxScoreMap().entrySet()) {
            player.notifyListener(eGamePlayerEventType.CurioMaxScoreAchieve.getValue(), new ValueFourParamArgs(entry.getValue(), entry.getKey()));
        }
    }

    public void checkPrivilegeExpire() {
        for (Map.Entry<Integer, UserCurioItemData> entry : curioItemDataMap.entrySet()) {
            for (CurioPrivilege privilege : entry.getValue().getPrivilegeList()) {
                if(checkPrivilegeExpire(privilege)){
                    entry.getValue().setUpdateOption();
                }
            }
        }
    }

    public void syncUserData() {
        if(userCurioData == null){
            return;
        }

        CurioProto.CurioDataSyncMsg.Builder builder = CurioMgr.getSyncBuilder(userCurioData
                ,curioItemDataMap
                ,skillDataMap
                ,countDataMap);

        player.sendPacket(Protocol.U_CURIO_SYNC_DATA, builder);

    }



    public synchronized void initUserData(){
        if(userCurioData == null){
            userCurioData = new UserCurioData();
            userCurioData.setInsertOption();
            userCurioData.setUserId(player.getUserId());
            userCurioData.setQualityDrawTimesMap(new HashMap<>());
            userCurioData.setBadgeLv(1);

            updateBadge();
        }
    }

    public boolean isSystemOpen(){
        return SystemOpenMgr.systemOpen(player, eSystemId.Curio.getValue());
    }

    private void changeValueRank() {
        try {
            if(userCurioData != null){
                RankMgr.changeUserRank(eBigRankType.Normal.getValue(), player.getUserId(), BigInteger.valueOf(userCurioData.getScore()), eRankType.CurioScoreValue.getValue(),"" + userCurioData.getBadgeLv());
            }
        } catch (Exception ex) {
            log.error(ex);
        }
    }

    public void curioItemRank(UserCurioItemData itemData){
        try{
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", itemData.getItemId());
            //通过接口查询
//            jsonObject.put("l", itemData.getLv());
//            jsonObject.put("l2", itemData.getStarLv());
//            jsonObject.put("q", itemData.getQuality());
            RankMgr.changeUserRank(eBigRankType.CurioItem.getValue(), player.getUserId(), BigInteger.valueOf(itemData.getScore()), eRankType.Curio.getValue(), jsonObject.toJSONString(), itemData.getScoreUpdateTime());
            RankMgr.changeUserRank(eBigRankType.CurioItem.getValue(), player.getUserId(), BigInteger.valueOf(itemData.getScore()), itemData.getItemId(), jsonObject.toJSONString(), itemData.getScoreUpdateTime());
        }catch (Exception e){

        }

        changeValueRank();
    }


    /**
     * 淘宝
     * @param type 类型
     */
    public int draw(int type) {
        if(!isSystemOpen()){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        CurioConfig config = CurioConfigMgr.getConfig();
        List<String> lotteryConsumeList = config.getLotteryConsumeList();
        if(lotteryConsumeList == null || lotteryConsumeList.size() != 3){
            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
        }

        Property consume = PropertyHelper.parseStringToProperty(lotteryConsumeList.get(0));
        int times = 1;
        if(type == 1){
            consume = PropertyHelper.parseStringToProperty(lotteryConsumeList.get(1));
            times = 10;
        } else if (type == 2) {
            // 判断下是否开启
            if (getBadgeLv() < GameConfig.CURIO_LOTTERY_CONTINUOUS_HUNDRED_COST_COND) {
                return GameErrorCode.E_SYSTEM_NO_OPEN;
            }
            consume = PropertyHelper.parseStringToProperty(lotteryConsumeList.get(2));
            times = 100;
        }

        Random random = new Random();
        List<CurioDrawItem> poolList = config.getCopyDrawItemList();
        if(poolList.size() == 0){
            return GameErrorCode.E_GAME_ERROR;
        }

        //背包是否足够
        if(!player.getModule(CurrencyModule.class).currencyIsEnough(consume)){
            //触发现金礼包
            player.notifyListener(eGamePlayerEventType.CurioRechargeTrigger.getValue(), 0);
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        if(Config.isDebug()) {
            CurioMgr.getLogger().info("抽奖池===========================");
            for (CurioDrawItem item : poolList) {
                CurioMgr.getLogger().info(item.getReward() + ";" + item.getWeight() + ";" + item.getQuality());
            }
        }

        List<CurioDrawResult> drawResult = new ArrayList<>();
        //公告
        CurioProto.CrossCurioLotteryUploadNoticeReqMsg.Builder noticeMsg = CurioProto.CrossCurioLotteryUploadNoticeReqMsg.newBuilder();

        //公告条件(碎片品质；升级道具配置)
        List<Integer> noticeCondition = StringUtils.stringToIntegerList(GameConfig.CURIO_NOTICE_COND, "\\|");

        //复制保底
        Map<Integer, Integer> minMap = copyMap(userCurioData.getQualityDrawTimesMap());
        //复制抽奖
        int curDrawTimes = userCurioData.getDrawTimes();

        //客户端要的格式
        List<String> allProperty = new ArrayList<>();

        //抽奖
        for (int i = 0; i < times; i++) {
            CurioDrawResult result = drawCurioDrawItem(minMap, curDrawTimes, random, poolList, i);
            curDrawTimes++;
            if(result != null){
                drawResult.add(result);
                //原始奖励
                allProperty.add(result.getReward());
            }
        }

        if(drawResult.size() != times){
            return GameErrorCode.E_GAME_ERROR;
        }

        //扣除消耗
        if(!player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.Curio, eLogMoneyType.CurioDrawConsume)){
            //触发现金礼包
            player.notifyListener(eGamePlayerEventType.CurioRechargeTrigger.getValue(), 0);
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        //更新状态
        userCurioData.setDrawTimes(times + userCurioData.getDrawTimes());
        userCurioData.setQualityDrawTimesMap(copyMap(minMap));

        Property property = new Property();
        for (CurioDrawResult result : drawResult) {
            property.addProperty(PropertyHelper.parseStringToProperty(result.getReward()));

            List<Integer> list = StringUtils.stringToIntegerList(result.getReward(), "=");
            if(list.size() > 0){
                GoodsInfo goodsInfo = GoodsMgr.getGoodsById(list.get(0));
                if(goodsInfo == null){
                    continue;
                }
                int needQuality = noticeCondition.get(1);
                if(goodsInfo.getType() == eGoodsType.CurioItemExchange.getValue()){
                    needQuality = noticeCondition.get(0);
                }
                //是否公告
                if(result.getQuality() >= needQuality && result.isWhole()) {
                    CurioProto.CurioLotteryNoticeMsg.Builder noticeBuilder = CurioProto.CurioLotteryNoticeMsg.newBuilder();
                    noticeBuilder.setUserId(player.getUserId());
                    noticeBuilder.setPlayerMsg(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
                    noticeBuilder.setGoodsId(result.getReward());
                    //如果是整卡
                    if(result.isWhole()){
                        //替换
                        List<Integer> integerList = StringUtils.stringToIntegerList(result.getReward(), "=");
                        if(integerList.size() == 2){
                            GoodsInfo goods = GoodsMgr.getGoodsById(integerList.get(0));
                            if(goods != null){
                                noticeBuilder.setGoodsId(goodsInfo.getParamList().get(0).intValue() + "=1");
                            }
                        }
                    }
                    noticeBuilder.setType(result.getQuality());
                    noticeBuilder.setTime(System.currentTimeMillis());
                    noticeMsg.addNotice(noticeBuilder);
                }
            }
        }

        //碎片转化
        List<Integer> convertList = new ArrayList<>();
        for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(entry.getKey());
            if(goodsInfo != null && goodsInfo.getType() == eGoodsType.CurioItemExchange.getValue()){
                convertList.add(goodsInfo.getGoodsId());
            }
        }

        Property exchangeReward = new Property();
        int totalProcess = 0;
        for (int exchangeId : convertList) {
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(exchangeId);
            CurioItemInfo itemInfo = config.getCurioItemInfo(goodsInfo.getParamList().get(0).intValue());
            //满星才转换
            if(itemInfo == null){
                continue;
            }
            if(!isItemStarMaxLv(itemInfo)){
                continue;
            }
            long num = property.getCountByGoodsId(exchangeId).longValue();
            long process = num * itemInfo.getOverflowChange();
            totalProcess += process;
            property.removeProperty(exchangeId);
            if(Config.isDebug()){
                CurioMgr.getLogger().info("碎片 {} = {} 转进度 {}", exchangeId, num, process);
            }
            exchangeReward.addProperty(exchangeId, BigInteger.valueOf(num));
        }

        //加奖励
        player.getModule(CurrencyModule.class).addCurrency(PropertyHelper.parsePropertyToString(property), eLogMoneyType.Curio, eLogMoneyType.CurioDrawReward);

        if(totalProcess > 0) {
            if(Config.isDebug()){
                CurioMgr.getLogger().info("碎片转进度增加 {}", totalProcess);
            }
            userCurioData.setRiverProcess(userCurioData.getRiverProcess() + totalProcess);
        }

        CurioProto.CurioLotteryDrawRespMsg.Builder builder = CurioProto.CurioLotteryDrawRespMsg.newBuilder();
        builder.setRet(0);
        builder.setUserData(CurioMgr.buildUserDataTemp(userCurioData));
        if (type == 2) {
            // 百连奖励汇总
            builder.setReward(PropertyHelper.parsePropertyToString(property));
        } else {
            builder.setReward(StringUtils.listToString(allProperty, ";"));
        }
        builder.setGiveGoods(PropertyHelper.parsePropertyToString(exchangeReward));
        player.sendPacket(Protocol.U_CURIO_LOTTERY_DRAW, builder);

        if(noticeMsg.getNoticeCount() > 0){
            noticeMsg.setPlayerMsg(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
            // 上公告
            player.sendPacket(Protocol.C_CURIO_LOTTERY_UPLOAD_NOTICE, noticeMsg);
        }

        //日志
        AutoLogMgr.add(new LogCurioLottery(
                player.getUserId(),
                type,
                PropertyHelper.parsePropertyToString(property)
        ));

        if(totalProcess > 0) {
            AutoLogMgr.add(new LogCurioRiverGift(
                    player.getUserId(),
                    totalProcess,
                    userCurioData.getRiverProcess(),
                    1,
                    PropertyHelper.parsePropertyToString(exchangeReward)
                    ));
        }
        return 0;
    }

    private Map<Integer, Integer> copyMap(Map<Integer, Integer> qualityDrawTimesMap) {
        Map<Integer, Integer> toMap = new HashMap<>();
        for (Map.Entry<Integer, Integer> entry : qualityDrawTimesMap.entrySet()) {
            toMap.put(entry.getKey(), entry.getValue());
        }
        return toMap;
    }

    /**
     * 进度转道具
     */
    private long processToRiverGoods(Property p) {
        //碎片转换进度
        long old = userCurioData.getRiverProcess();
        long getGoodsNum = userCurioData.getRiverProcess() / CurioConfigMgr.getConfig().getSchedule();
        if(getGoodsNum > 0){
            p.addProperty(PropertyHelper.parseStringToProperty(CurioConfigMgr.getConfig().getScheduleReward()));
            p.rideProperty(getGoodsNum);
            userCurioData.setRiverProcess((userCurioData.getRiverProcess() % CurioConfigMgr.getConfig().getSchedule()));
            player.getModule(CurrencyModule.class).addCurrency(p, eLogMoneyType.Curio, eLogMoneyType.CurioScheduleToGoods);
            if(Config.isDebug()){
                CurioMgr.getLogger().info(" 进度转山河赠礼 {}", PropertyHelper.parsePropertyToString(p));
            }
        }
        return old - userCurioData.getRiverProcess();
    }

    /**
     * 是否达到最高星级
     * @param itemInfo 藏品配置
     * @return
     */
    private boolean isItemStarMaxLv(CurioItemInfo itemInfo) {
        //无藏品时
        UserCurioItemData itemData = getUserCurioItemData(itemInfo.getId());
        if(itemData == null){
            return false;
        }
        //星级加成最大了，不必升级
        if(itemData.getStarLv() >= itemInfo.getBaseSkillFixedAdd().size()){
            return true;
        }
        //没有技能就是满星
//        if(itemInfo.getSpecialSkill() <= 0){
//            return true;
//        }
//        UserCurioSkillData skillData = skillDataMap.get(itemInfo.getSpecialSkill());
//        if(skillData == null){
//            if(Config.isDebug()){
//                CurioMgr.getLogger().info("藏品{}，前置条件为满足 {}", itemInfo, itemInfo.getSpecialSkill());
//            }
//        }
//        SkillInfo skillInfo = SkillMgr.getSkillInfo(itemInfo.getSpecialSkill());
//        if(skillInfo == null){
//            return false;
//        }
//        int maxLv = SkillMgr.getSkillMaxLvByUpgradeType(skillInfo.getUpgradeType(0));
//        if(maxLv <= itemData.getStarLv()){
//            return true;
//        }
        return false;
    }

    /**
     * 抽奖
     * @param minMap 保底状态
     * @param curDrawTimes 当前总抽奖次数
     * @param random 随机
     * @param poolList 抽奖池
     * @param no 10连中的抽次
     * @return
     */
    public CurioDrawResult drawCurioDrawItem(Map<Integer, Integer> minMap, int curDrawTimes, Random random, List<CurioDrawItem> poolList, int no) {

        //最低品质
        int lowQuality = 0;
        //保底高品质
        List<CurioDrawControl> drawControlList = CurioConfigMgr.getConfig().getDrawControlList();

        for (int i = drawControlList.size() - 1; i >= 0; i--) {
            CurioDrawControl control = drawControlList.get(i);
            int times = minMap.getOrDefault(control.getQuality(), 0);
            if(times + 1 >= control.getDrawTimes()){
                lowQuality = control.getQuality();
                break;
            }
        }

        List<CurioDrawItem> itemList = new ArrayList<>();
        List<Integer> weightList = new ArrayList<>();
        for (CurioDrawItem drawItem : poolList) {
            if(drawItem.getQuality() >= lowQuality) {
                itemList.add(drawItem);
                weightList.add(drawItem.getWeight());
            }
        }

        if(itemList.size() == 0){
            return null;
        }

        int idx = RandomHelper.getRandomIndexByWeight(weightList, random);
        CurioDrawItem item = itemList.get(idx);

        //新手引导，前10抽，改变抽奖结果
        if(curDrawTimes < 10){
            String reward = CurioConfigMgr.getConfig().getLottery10RewardList().get(curDrawTimes);
            List<Integer> goodsIdNum = StringUtils.stringToIntegerList(reward, "=");
            if(goodsIdNum.size() != 2){
                return null;
            }
            GoodsInfo goodsInfo = GoodsMgr.getGoodsById(goodsIdNum.get(0));
            if(goodsInfo == null){
                return null;
            }
            //是否是碎片
            if(goodsInfo.getType() == eGoodsType.CurioItemExchange.getValue()) {
                CurioItemInfo curioItemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(goodsInfo.getParamList().get(0).intValue());
                if (curioItemInfo == null) {
                    return null;
                }
                boolean whole = false;
                CurioDrawItem curioDrawItemByReward = CurioConfigMgr.getConfig().getCurioDrawItemByReward(reward);
                item = new CurioDrawItem(reward, 0);
                if (curioDrawItemByReward != null) {
                    whole = curioDrawItemByReward.isWhole();
                    //整品才有品质
                    item.setQuality(curioItemInfo.getQuality());
                }
                item.setWhole(whole);
            }else {
                //普通碎片
                item = new CurioDrawItem(reward, 0);
            }
        }

        CurioDrawResult result = CurioDrawResult.copy(item, no);

        //保底统计（+1）
        for (int i = drawControlList.size() - 1; i >= 0; i--) {
            CurioDrawControl control = drawControlList.get(i);
            int old = minMap.getOrDefault(control.getQuality(), 0);
            minMap.put(control.getQuality(), 1 + old);
        }

        lowQuality = item.getQuality();

        if(lowQuality > 0){
            //触发保底要重置
            for (int i = drawControlList.size() - 1; i >= 0; i--) {
                CurioDrawControl control = drawControlList.get(i);
                if(control.getQuality() <= lowQuality) {
                    if(minMap.containsKey(control.getQuality())) {
                        minMap.put(control.getQuality(), 0);
                    }
                    if (Config.isDebug()) {
                        CurioMgr.getLogger().info("play {} 触发保底 {}", player.getUserId(), lowQuality);
                    }
                }
            }
        }
        return result;
    }

    /**
     * 兑换碎片
     * @param consumeItemId 碎片id
     * @return
     */
    public int exchange(int consumeItemId) {
        if(!isSystemOpen()){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        GoodsInfo goodsInfo = GoodsMgr.getGoodsById(consumeItemId);
        if(goodsInfo == null){
            return GameErrorCode.E_GOODS_NO_EXIST;
        }
        if(goodsInfo.getType() != eGoodsType.CurioItemExchange.getValue()){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }

        int curioItemId = goodsInfo.getParamList().get(0).intValue();
        CurioItemInfo itemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(curioItemId);
        if(itemInfo == null){
            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
        }

        if(curioItemDataMap.containsKey(curioItemId)){
            return GameErrorCode.E_CURIO_ITEM_HAD_GET;
        }

        Integer num = CurioConfigMgr.getConfig().getExchangeCostMap().get(itemInfo.getQuality());
        if(num == null){
            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
        }

        //扣除
        if(!player.getModule(CurrencyModule.class).removeCurrency(PropertyHelper.parseStringToProperty(consumeItemId + "=" + num),
                eLogMoneyType.Curio, eLogMoneyType.CurioExchangeConsume)){
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        CurioProto.CurioCollectionRespMsg.Builder builder = CurioProto.CurioCollectionRespMsg.newBuilder();

        //藏品初始化
        UserCurioItemData itemData = initUserCurioItemData(itemInfo);

        curioItemDataMap.put(itemInfo.getId(), itemData);

        UserCurioSkillData baseSkill = skillDataMap.get(itemInfo.getBaseSkill());
        if(baseSkill != null){
            CurioMgr.calSkillAddition(baseSkill, player);
            builder.addSkill(CurioMgr.buildSkillTemp(baseSkill));
        }

        if(itemInfo.getSpecialSkill() > 0) {
            SkillInfo skillInfo = SkillMgr.getSkillInfo(itemInfo.getSpecialSkill());
            if (skillInfo != null && skillInfo.getType() == eSkillType.ManorAnimalOutputSkill.getValue()) {
                ManorHarvestModel harvestModel = player.getModule(ManorModule.class).getHarvestModel();
                if (harvestModel != null) {
                    harvestModel.calcAnimalYield();
                }
            }
        }

        UserCurioSkillData skillData = skillDataMap.get(itemInfo.getSpecialSkill());
        if(skillData != null){
            CurioMgr.calSkillAddition(skillData, player);
            builder.addSkill(CurioMgr.buildSkillTemp(skillData));
        }

        //计算评分
        CurioMgr.calScore(userCurioData, curioItemDataMap);

        //星级解锁特权
        unlockItemPrivilege(itemData.getStarLv() - 1, itemData);

        CurioMgr.uploadAllServerMaxScore(itemData, player.getUserId());

        curioItemRank(itemData);

        builder.setRet(0);
        builder.setUserData(CurioMgr.buildUserDataTemp(userCurioData));
        builder.setItem(CurioMgr.buildCurioItemTemp(itemData));
        player.sendPacket(Protocol.U_CURIO_COLLECTION, builder);

        //日志
        AutoLogMgr.add(new LogCurioItemGet(
                player.getUserId(),
                itemData.getItemId(),
                itemInfo.getQuality(),
                CurioConfigMgr.getConfig().getSuitList(itemData.getItemId()),
                itemData.getScore()
        ));

        //聊天频道分享
        sendMessage(itemData, eMessageType.CurioCollectShare);
        return 0;
    }

    /**
     * 初始化藏品特殊效果
     * @param itemData 藏品
     * @param itemInfo 藏品配置
     */
    private void initItemSpecialSkill(UserCurioItemData itemData, CurioItemInfo itemInfo) {
        if(StringUtils.isNullOrEmpty(itemInfo.getSpecialSkillCond())){
            return;
        }
        //无需解锁条件且没有配置技能
        if("0".equals(itemInfo.getSpecialSkillCond()) && itemInfo.getSpecialSkill() <= 0){
            return;
        }
        if(itemInfo.getSpecialSkill() <= 0){
            return;
        }
        if(skillDataMap.containsKey(itemInfo.getSpecialSkill())){
            return;
        }
        //初始特殊效果
        if(unlockCondition(itemInfo.getSpecialSkillCond())){
            UserCurioSkillData skillData = new UserCurioSkillData();
            skillData.setUserId(player.getUserId());
            skillData.setObjId(itemData.getItemId());
            skillData.setSkill(itemInfo.getSpecialSkill());
            skillData.setSkillType(eCurioSkillType.CurioItemSpecialSkill.getType());
            skillData.setLv(itemData.getStarLv());
            skillData.setInsertOption();
            addSkill(skillData);
        }
    }

    public void checkAllCurioItemSpecialSkill(){
        for (Map.Entry<Integer, UserCurioItemData> dataEntry : curioItemDataMap.entrySet()) {
            UserCurioItemData itemData = dataEntry.getValue();
            CurioItemInfo itemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(itemData.getItemId());
            if(itemInfo == null){
                continue;
            }
            initItemSpecialSkill(itemData, itemInfo);
        }
    }

    /**
     * 是否解锁特殊效果条件
     */
    public boolean unlockCondition(String specialSkillCond) {
        //无需解锁条件
        if("0".equals(specialSkillCond)){
            return true;
        }
        List<String> paramsList = StringUtils.stringToStringList(specialSkillCond, "=");
        if(paramsList.size() != 2){
            return false;
        }
        int type = Integer.parseInt(paramsList.get(0));
        List<Integer> paramValues = StringUtils.stringToIntegerList(paramsList.get(1), ";");
        return CurioMgr.unlockCondition(type, paramValues, player);
    }

    /**
     * 初始藏品
     * @param itemInfo 藏品配置
     */
    public UserCurioItemData initUserCurioItemData(CurioItemInfo itemInfo) {
        UserCurioItemData itemData = new UserCurioItemData();
        itemData.setLv(1);
        itemData.setStarLv(1);
        itemData.setItemId(itemInfo.getId());
        itemData.setUserId(player.getUserId());
        itemData.setQuality(itemInfo.getQuality());
        itemData.setPrivilegeList(new ArrayList<>());
        itemData.setInsertOption();

        //解锁基础技能
        UserCurioSkillData skillData = new UserCurioSkillData();
        skillData.setUserId(player.getUserId());
        skillData.setSkill(itemInfo.getBaseSkill());
        skillData.setLv(itemData.getLv());
        skillData.setSkillType(eCurioSkillType.CurioItemSkill.getType());
        skillData.setObjId(itemInfo.getId());
        skillData.setInsertOption();
        addSkill(skillData);

        //解锁特殊技能
        initItemSpecialSkill(itemData, itemInfo);
        return itemData;
    }

//    /**
//     * 激活套装
//     * @param suitId 套装
//     */
//    public int activeSuit(int suitId) {
//
//        if(!isSystemOpen()){
//            return GameErrorCode.E_SYSTEM_NO_OPEN;
//        }
//        CurioItemSuitInfo suitInfo = CurioConfigMgr.getConfig().getCurioItemSuitInfo(suitId);
//        if(suitInfo == null){
//            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
//        }
//
//        SkillInfo skillInfo = SkillMgr.getSkillInfo(suitInfo.getSkill());
//        if(skillInfo == null){
//            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
//        }
//
//        //当前等级
//        int lv = 0;
//        UserCurioSkillData skillData = skillDataMap.get(skillInfo.getId());
//        if(skillData != null){
//            lv = skillData.getLv();
//        }
//
//        //下一级
//        SkillUpgradeInfo upgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), lv);
//        if(upgradeInfo == null){
//            return GameErrorCode.E_CURIO_ITEM_LEVEL_MAX;
//        }
//
//        //隐藏的藏品，不然激活
//        for (Integer cId : suitInfo.getCurioList()) {
//            CurioItemInfo itemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(cId);
//            if(itemInfo == null){
//                return GameErrorCode.E_CURIO_ITEM_SUIT_HIDE;
//            }
//        }
//
//        long starNum = upgradeInfo.getConsumeCount();
//
//        //遍历组合内藏品星级
//        if(suitInfo.getSkillUpgradeCostType() == 1) {
//            //全部星级
//            for (int id : suitInfo.getCurioList()) {
//                if (!curioItemDataMap.containsKey(id)) {
//                    return GameErrorCode.E_CURIO_ITEM_SUIT_ACTIVE_FAIL;
//                }
//                UserCurioItemData itemData = curioItemDataMap.get(id);
//                if (itemData.getStarLv() < starNum) {
//                    return GameErrorCode.E_CURIO_ITEM_UPGRADE_CONDITION_NO_ENOUGH;
//                }
//            }
//        }else {
//            //总星级
//            int totalStar = 0;
//            for (int id : suitInfo.getCurioList()) {
//                if (curioItemDataMap.containsKey(id)) {
//                    totalStar += curioItemDataMap.get(id).getStarLv();
//                }
//            }
//            if(totalStar < starNum){
//                return GameErrorCode.E_CURIO_ITEM_UPGRADE_CONDITION_NO_ENOUGH;
//            }
//        }
//
//        if(!skillDataMap.containsKey(suitInfo.getSkill())){
//
//            skillData = new UserCurioSkillData();
//            skillData.setUserId(player.getUserId());
//            skillData.setObjId(suitId);
//            skillData.setSkill(suitInfo.getSkill());
//            skillData.setSkillType(eCurioSkillType.CurioItemSuitSkill.getType());
//            skillData.setLv(1);
//            skillData.setInsertOption();
//            addSkill(skillData);
//
//        }else {
//            //已激活的套装，进行技能升级
//            skillData = skillDataMap.get(suitInfo.getSkill());
//            skillData.setLv(1 + skillData.getLv());
//        }
//
//        CurioMgr.calSkillAddition(skillData, player);
//
//        CurioProto.CurioSuiteActiveRespMsg.Builder builder = CurioProto.CurioSuiteActiveRespMsg.newBuilder().setRet(0);
//        builder.setUserData(CurioMgr.buildUserDataTemp(userCurioData));
//        builder.setSkill(CurioMgr.buildSkillTemp(skillData));
//        player.sendPacket(Protocol.U_CURIO_SUITE_ACTIVE, builder);
//
//        //日志
//        AutoLogMgr.add(new LogCurioSuitActive(
//            player.getUserId(),
//                suitId,
//                skillData.getSkill(),
//                skillData.getLv()
//        ));
//        return 0;
//    }


    /**
     * 激活套装
     * @param suitId 套装
     */
    public int activeSuit(int suitId) {
        if(!isSystemOpen()){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        CurioItemSuitInfo suitInfo = CurioConfigMgr.getConfig().getCurioItemSuitInfo(suitId);
        if(suitInfo == null){
            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
        }

        //套装技能激活/升级
        CurioProto.CurioSuiteActiveRespMsg.Builder builder = CurioProto.CurioSuiteActiveRespMsg.newBuilder();
        int ret = 0;
        List<Integer> skillList = suitInfo.getSkillList();//获取套装技能id列表
        for (int skillId : skillList) {
            try {
                //技能升级
                UserCurioSkillData skillData = this.activeSuitOne(suitInfo, skillId);
                builder.addSkill(CurioMgr.buildSkillTemp(skillData));
            } catch (BusinessException e) {
                ret = e.getCode();
            }
        }

        //返回，只要升级成功一个技能就返回升级成功
        if (builder.getSkillCount() > 0) {
            builder.setRet(0);
            builder.setUserData(CurioMgr.buildUserDataTemp(userCurioData));
            player.sendPacket(Protocol.U_CURIO_SUITE_ACTIVE, builder);
            return 0;
        } else {
            return ret;
        }
    }

    /**
     * 藏品套装升级-升级一个技能
     * @param suitInfo
     * @param skillId
     * @return
     * @throws BusinessException
     */
    private UserCurioSkillData activeSuitOne(CurioItemSuitInfo suitInfo, int skillId) throws BusinessException {
        int suitId = suitInfo.getId();
        SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
        if(skillInfo == null){
            log.error("藏品-套装升级-技能不存在：{}", skillId);
            throw BusinessException.newException(GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION);
        }

        //当前等级
        int lv = 0;
        UserCurioSkillData skillData = skillDataMap.get(skillInfo.getId());
        if(skillData != null){
            lv = skillData.getLv();
        }

        //下一级
        SkillUpgradeInfo upgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), lv);
        if(upgradeInfo == null){
            log.error("藏品-套装升级-技能升级配置不存在：{}, {}, {}", skillId, skillInfo.getUpgradeType(0), lv);
            throw BusinessException.newException(GameErrorCode.E_CURIO_ITEM_LEVEL_MAX);
        }

        //隐藏的藏品，不然激活
        boolean checkFlag = true;
        for (Integer cId : suitInfo.getCurioList()) {
            CurioItemInfo itemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(cId);
            if(itemInfo == null){
                checkFlag = false;
                break;
            }
        }
        if(!checkFlag){
            log.error("藏品-套装升级-套装已隐藏：{}, {}, {}", suitId, skillId);
            throw BusinessException.newException(GameErrorCode.E_CURIO_ITEM_SUIT_HIDE);
        }

        long starNum = upgradeInfo.getConsumeCount();

        //遍历组合内藏品星级
        if(suitInfo.getSkillUpgradeCostType() == 1) {
            //全部星级
            boolean conCheckFlag = true;
            for (int id : suitInfo.getCurioList()) {
                if (!curioItemDataMap.containsKey(id)) {
                    conCheckFlag = false;
                    break;
                }
                UserCurioItemData itemData = curioItemDataMap.get(id);
                if (itemData.getStarLv() < starNum) {
                    conCheckFlag = false;
                    break;
                }
            }
            if(!conCheckFlag){
                log.info("藏品-套装升级-套装激活条件不足：{}, {}", suitId, skillId);
                throw BusinessException.newException(GameErrorCode.E_CURIO_ITEM_UPGRADE_CONDITION_NO_ENOUGH);
            }
        }else {
            //总星级
            int totalStar = 0;
            for (int id : suitInfo.getCurioList()) {
                if (curioItemDataMap.containsKey(id)) {
                    totalStar += curioItemDataMap.get(id).getStarLv();
                }
            }
            if(totalStar < starNum){
                log.info("藏品-套装升级-套装激活条件不足：{}, {}, {}", suitId, skillId, totalStar, starNum);
                throw BusinessException.newException(GameErrorCode.E_CURIO_ITEM_UPGRADE_CONDITION_NO_ENOUGH);
            }
        }

        if(!skillDataMap.containsKey(skillId)){
            skillData = new UserCurioSkillData();
            skillData.setUserId(player.getUserId());
            skillData.setObjId(suitId);
            skillData.setSkill(skillId);
            skillData.setSkillType(eCurioSkillType.CurioItemSuitSkill.getType());
            skillData.setLv(1);
            skillData.setInsertOption();
            addSkill(skillData);

        }else {
            //已激活的套装，进行技能升级
            skillData = skillDataMap.get(skillId);
            skillData.setLv(1 + skillData.getLv());
        }

        CurioMgr.calSkillAddition(skillData, player);

        //日志
        AutoLogMgr.add(new LogCurioSuitActive(
                player.getUserId(),
                suitId,
                skillData.getSkill(),
                skillData.getLv()
        ));

        //返回
        return skillData;
    }

    /**
     * 升级
     * @param itemId 藏品
     * @param type 类型
     * @return
     */
    public int upgradeLv(int itemId, int type) {
        if(!isSystemOpen()){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        UserCurioItemData itemData = getUserCurioItemData(itemId);
        if(itemData == null){
            return GameErrorCode.E_CURIO_ITEM_NO_GET;
        }
        CurioItemInfo itemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(itemData.getItemId());
        if(itemInfo == null){
            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
        }

        UserCurioSkillData skillData = skillDataMap.get(itemInfo.getBaseSkill());
        if(skillData == null){
            return GameErrorCode.E_GAME_ERROR;
        }

        SkillInfo skillInfo = SkillMgr.getSkillInfo(itemInfo.getBaseSkill());
        if(skillInfo == null){
            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
        }

        int times = 1;
        if(type == 1){
            BigInteger limit = new BigInteger(GameConfig.CURIO_LOTTERY_CONTINUOUS_TEN_COST_COND);
            if(limit.compareTo(BigInteger.valueOf(userCurioData.getScore())) > 0){
                return GameErrorCode.E_CURIO_UPGRADE_TEN_SCORE_NO_ENOUGH;
            }
            times = 10;
        }
        int realTimes = 0;
        long oldScore = itemData.getScore();
        int ret = 0;

        int firstFindId = 0;

        if(skillInfo.getType() == eSkillType.ManorAnimalOutputSkill.getValue()){
            ManorHarvestModel harvestModel = player.getModule(ManorModule.class).getHarvestModel();
            if(harvestModel != null){
                harvestModel.calcAnimalYield();
            }
        }

        for (int i = 0; i < times; i++) {

            if(skillData.getLv() >= skillInfo.getMaxLevel()){
                ret = GameErrorCode.E_CURIO_ITEM_LEVEL_MAX;
                break;
            }

            SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), skillData.getLv());
            if(skillUpgradeInfo == null){
                ret = GameErrorCode.E_CURIO_ITEM_LEVEL_MAX;
                break;
            }

            Property consume = new Property();

            int findId = 0;
            long needNum = skillUpgradeInfo.getConsumeCount();
            if(needNum <= 0){
               break;
            }

            //拿道具
            List<GoodsInfo> goodsInfoList = GoodsMgr.getGoodsListByType(eGoodsType.CurioItemUpgradeConsume.getValue());
            for (GoodsInfo goodsInfo : goodsInfoList) {
                //判断等级
                if(itemData.getLv() >= goodsInfo.getParamList().get(0).intValue() && itemData.getLv() <= goodsInfo.getParamList().get(1).intValue()){
                    findId = goodsInfo.getGoodsId();
                    break;
                }
            }
            if(findId > 0){
                if(firstFindId == 0){
                    firstFindId = findId;
                }
                if(findId != firstFindId){
                    //升级中止
                    break;
                }
                consume.addProperty(findId, needNum);
            }else {
                ret = GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
                break;
            }

            if(!player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.Curio, eLogMoneyType.CurioItemUpgradeConsume)){
                //触发现金礼包
                player.notifyListener(eGamePlayerEventType.CurioRechargeTrigger.getValue(), 0);
                ret = GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
                break;
            }

            itemData.setLv(1 + itemData.getLv());
            skillData.setLv(1 + skillData.getLv());

            realTimes++;
        }

        if(realTimes == 0){
            return ret;
        }

        CurioMgr.calSkillAddition(skillData, player);
        CurioMgr.calScore(userCurioData, curioItemDataMap);

        CurioMgr.uploadAllServerMaxScore(itemData, player.getUserId());

        curioItemRank(itemData);

        CurioProto.CurioItemUpgradeRespMsg.Builder builder = CurioProto.CurioItemUpgradeRespMsg.newBuilder();
        builder.setRet(0);
        builder.setUserData(CurioMgr.buildUserDataTemp(userCurioData));
        builder.setItem(CurioMgr.buildCurioItemTemp(itemData));
        builder.setSkill(CurioMgr.buildSkillTemp(skillData));
        player.sendPacket(Protocol.U_CURIO_ITEM_UPGRADE, builder);

        //日志
        AutoLogMgr.add(new LogCurioItemUpgrade(
                player.getUserId(),
                itemData.getItemId(),
                itemData.getLv() - realTimes,
                itemData.getLv(),
                itemData.getScore() - oldScore
        ));
        return 0;
    }

    /**
     * 升星(用碎片)
     * @param itemId 藏品
     * @param consumeId 消耗的道具
     * @return
     */
    public int upgradeStarLv(int itemId, int consumeId) {
        if(!isSystemOpen()){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        UserCurioItemData itemData = getUserCurioItemData(itemId);
        if(itemData == null){
            return GameErrorCode.E_CURIO_ITEM_NO_GET;
        }

        if(consumeId > 0) {
            GoodsInfo consumeGoodsInfo = GoodsMgr.getGoodsById(consumeId);
            if (consumeGoodsInfo == null) {
                return GameErrorCode.E_GOODS_NO_EXIST;
            }
            if (consumeGoodsInfo.getType() != eGoodsType.CurioItemExchange.getValue()) {
                return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
            }
            if (itemData.getLv() < consumeGoodsInfo.getParamList().get(0).intValue() || itemData.getLv() > consumeGoodsInfo.getParamList().get(1).intValue()) {
                return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
            }
        }

        CurioItemInfo itemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(itemData.getItemId());
        if(itemInfo == null){
            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
        }

        SkillUpgradeInfo skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(itemInfo.getStarUpgradeType(), itemData.getStarLv());
        if(skillUpgradeInfo == null){
            return GameErrorCode.E_CURIO_ITEM_LEVEL_MAX;
        }

        //看看isItemStarMaxLv
        if(itemData.getStarLv() >= itemInfo.getBaseSkillFixedAdd().size()){
            return GameErrorCode.E_CURIO_ITEM_LEVEL_MAX;
        }

        Property consume = new Property();
        int findId = 0;
        if(consumeId > 0){
              return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
//            consume.addProperty(consumeId, skillUpgradeInfo.getConsumeCount());
//            if(!player.getModule(CurrencyModule.class).currencyIsEnough(consume)){
//                return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
//            }
        }else {
            //先看碎片够不够
            //先拿碎片
            long needNum = skillUpgradeInfo.getConsumeCount();
            List<GoodsInfo> goodsInfoList = GoodsMgr.getGoodsListByType(eGoodsType.CurioItemExchange.getValue());
            for (GoodsInfo goodsInfo : goodsInfoList) {
                //判断碎片
                if(goodsInfo.getParamList().get(0).intValue() == itemId){
                    findId = goodsInfo.getGoodsId();
                    break;
                }
            }
            if(findId > 0) {
                consume.addProperty(findId, needNum);
            }else {
                return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
            }
        }

        if(!player.getModule(CurrencyModule.class).removeCurrency(consume, eLogMoneyType.Curio, eLogMoneyType.CurioItemUpgradeStarConsume)){
            return GameErrorCode.E_BAG_ITEM_NO_ENOUGH;
        }

        //庄园先结算一次
        SkillInfo skillInfo1 = SkillMgr.getSkillInfo(itemInfo.getSpecialSkill());
        if(skillInfo1 != null && skillInfo1.getType() == eSkillType.ManorAnimalOutputSkill.getValue()){
            ManorHarvestModel harvestModel = player.getModule(ManorModule.class).getHarvestModel();
            if(harvestModel != null){
                harvestModel.calcAnimalYield();
            }
        }

        CurioProto.CurioItemStarUpgradeRespMsg.Builder builder = CurioProto.CurioItemStarUpgradeRespMsg.newBuilder();

        itemData.setStarLv(1 + itemData.getStarLv());

        //基础技能效果重新计算
        UserCurioSkillData baseSkill = getSkill(itemInfo.getBaseSkill());
        if(baseSkill != null){
            CurioMgr.calSkillAddition(baseSkill, player);
            builder.addSkill(CurioMgr.buildSkillTemp(baseSkill));
        }

        UserCurioSkillData skillData = skillDataMap.get(itemInfo.getSpecialSkill());
        if(skillData != null){
            //特殊效果是否升级，需要另外判断，不是一级对一级
            SkillInfo skillInfo = SkillMgr.getSkillInfo(itemInfo.getSpecialSkill());
            if(skillInfo != null){
                if(skillData.getLv() < skillInfo.getMaxLevel()){
                    //注意取特殊效果的技能等级
                    skillUpgradeInfo = SkillMgr.getSkillUpgradeInfo(skillInfo.getUpgradeType(0), skillData.getLv());
                    if(skillUpgradeInfo != null && skillUpgradeInfo.getConsumeCount() > 0){
                        //判断藏品星数是否足够
                        if(itemData.getStarLv() >= skillUpgradeInfo.getConsumeCount()) {
                            skillData.setLv(1 + skillData.getLv());
                            CurioMgr.calSkillAddition(skillData, player);
                        }
                    }
                }
            }
        }

        long oldScore = itemData.getScore();

        CurioMgr.calScore(userCurioData, curioItemDataMap);

        //满级，碎片转进度，进度转道具
        long addProcess = 0;
        if(isItemStarMaxLv(itemInfo)){
            //碎片数量
            long suiPianNum = player.getModule(BagModule.class).getUserBagItemCount(findId);
            if(suiPianNum > 0 && player.getModule(CurrencyModule.class).removeCurrency(PropertyHelper.parseStringToProperty(findId + "="+ suiPianNum),
                    eLogMoneyType.Curio, eLogMoneyType.CurioExchangeToSchedule)) {
                addProcess = suiPianNum * itemInfo.getOverflowChange();
                userCurioData.setRiverProcess(addProcess + userCurioData.getRiverProcess());
            }
            builder.setGiveGoods(findId + "=" + suiPianNum);
        }

        //星级解锁特权
        unlockItemPrivilege(itemData.getStarLv() - 1, itemData);

        CurioMgr.uploadAllServerMaxScore(itemData, player.getUserId());

        curioItemRank(itemData);

        builder.setRet(0);
        builder.setUserData(CurioMgr.buildUserDataTemp(userCurioData));
        builder.setItem(CurioMgr.buildCurioItemTemp(itemData));

        if(skillData != null) {
            builder.addSkill(CurioMgr.buildSkillTemp(skillData));
        }
        player.sendPacket(Protocol.U_CURIO_ITEM_UPGRADE_START, builder);

        //日志
        AutoLogMgr.add(new LogCurioItemStarUpgrade(
                player.getUserId(),
                itemData.getItemId(),
                itemData.getStarLv() - 1,
                itemData.getStarLv(),
                itemData.getScore() - oldScore
        ));

        if(addProcess > 0){
            AutoLogMgr.add(new LogCurioRiverGift(
                    player.getUserId(),
                    addProcess,
                    userCurioData.getRiverProcess(),
                    2,
                    builder.getGiveGoods()
            ));
        }

        //聊天频道分享
        sendMessage(itemData, eMessageType.CurioUpgradeShare);
        return 0;
    }

    public void sendMessage(UserCurioItemData itemData, eMessageType curioUpgradeShare) {
        //品质判断
        CurioItemInfo curioItemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(itemData.getItemId());
        if(curioItemInfo == null || curioItemInfo.getQuality() < 5){
            return;
        }
        //聊天条件
        if(!CurioConfigMgr.getConfig().getChatCondList().contains(itemData.getStarLv())){
            return;
        }

        WorldMessageProto.WorldMessageTempMsg.Builder chatMsg = WorldMessageProto.WorldMessageTempMsg.newBuilder();
        chatMsg.setUserId(player.getUserId());
        chatMsg.setSendTime(DateHelper.getCurrentSecond());
        chatMsg.setType(curioUpgradeShare.getValue());
        chatMsg.setPlayerBaseData(PlayerPb.parsePlayerBaseTempMsg(player.getUserInfo()));
        List<String> paramsList = new ArrayList<>();
        paramsList.add(String.valueOf(itemData.getItemId()));
        paramsList.add(String.valueOf(itemData.getLv()));
        paramsList.add(String.valueOf(itemData.getStarLv()));
        paramsList.add(String.valueOf(itemData.getScore()));
        chatMsg.setContent(StringUtils.listToString(paramsList, "\\|"));
        WorldMessageMgr.addWorldMessageMsgToList(player.getUserId(), chatMsg);
    }

    /**
     * 解锁特权，星级变动时候，才可以调用
     */
    private void unlockItemPrivilege(int oldStar, UserCurioItemData itemData) {
        CurioItemInfo curioItemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(itemData.getItemId());
        boolean change = false;
        for (Map.Entry<Integer, List<CurioPrivilegeDay>> entry : curioItemInfo.getPrivilegeDayMap().entrySet()) {
            int type = entry.getKey();
            List<CurioPrivilegeDay> value = entry.getValue();
            CurioPrivilege itemPrivilege = getCurioItemPrivilege(type, itemData);

            //如果是0级，只能处理未解锁的
            if(oldStar == 0 && itemPrivilege != null){
                continue;
            }

            for (CurioPrivilegeDay privilegeDay : value) {
                if(privilegeDay.getStar() > oldStar && privilegeDay.getStar() <= itemData.getStarLv()){
                    if(itemPrivilege == null){
                        itemPrivilege = new CurioPrivilege();
                        itemPrivilege.setType(type);
                        itemPrivilege.setUse(false);
                        itemData.getPrivilegeList().add(itemPrivilege);
                        change = true;
                    }
                    if(itemPrivilege.getExpire() != -1 && privilegeDay.getAddDay() == -1){
                        itemPrivilege.setExpire(-1);
                        change = true;
                        continue;
                    }
                    if(itemPrivilege.getExpire() <= DateHelper.getCurrentSecond()){
                        itemPrivilege.setExpire(DateHelper.getCurrentSecond() + privilegeDay.getAddDay() * DateHelper.DAY_SECONDS);
                        change = true;
                        continue;
                    }
                    if(itemPrivilege.getExpire() > DateHelper.getCurrentSecond()) {
                        itemPrivilege.setExpire(itemPrivilege.getExpire() + privilegeDay.getAddDay() * DateHelper.DAY_SECONDS);
                        change = true;
                    }
                }
            }
        }
        if(change){
            itemData.setUpdateOption();
        }
    }

    /**
     * 勋章升级
     */
    public int badgeUpgrade() {
        if(!isSystemOpen()){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        CurioMgr.calScore(userCurioData, curioItemDataMap);

        CurioBadgeInfo badgeInfo = CurioConfigMgr.getConfig().getBadgeInfo(userCurioData.getBadgeLv());
        if (badgeInfo == null) {
            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
        }
        if (badgeInfo.getUnlockValue() <= 0){
            return GameErrorCode.E_CURIO_ITEM_LEVEL_MAX;
        }

        if (userCurioData.getScore() < badgeInfo.getUnlockValue()) {
            return GameErrorCode.E_CURIO_ITEM_UPGRADE_CONDITION_NO_ENOUGH;
        }
        userCurioData.setBadgeLv(1 + userCurioData.getBadgeLv());

        CurioProto.CurioBadgeUpgradeRespMsg.Builder builder = CurioProto.CurioBadgeUpgradeRespMsg.newBuilder();
        builder.setRet(0);
        builder.setUserData(CurioMgr.buildUserDataTemp(userCurioData));
        player.sendPacket(Protocol.U_CURIO_BADGE_UPGRADE, builder);

        player.getModule(EarnSpeedModule.class).scheduleAddSilver();

        //日志
        AutoLogMgr.add(new LogCurioBadgeUpgrade(
                player.getUserId(),
                userCurioData.getBadgeLv() - 1,
                userCurioData.getBadgeLv()
        ));

        changeValueRank();

        updateBadge();
        return 0;
    }

    /**
     * 领取山河进度奖励
     */
    public int riverReward() {
        if(!isSystemOpen()){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        if(userCurioData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        if(userCurioData.getRiverProcess() < CurioConfigMgr.getConfig().getSchedule()){
            return GameErrorCode.E_CURIO_RIVER_PROCESS_NO_ENOUGH;
        }

        CurioProto.CurioGetRiverGiveRewardRespMsg.Builder respMsg = CurioProto.CurioGetRiverGiveRewardRespMsg.newBuilder();
        respMsg.setRet(0);

        Property p = new Property();
        long process = processToRiverGoods(p);
        if(!p.isNothing()){
            respMsg.setReward(PropertyHelper.parsePropertyToString(p));
        }
        respMsg.setUserData(CurioMgr.buildUserDataTemp(userCurioData));
        respMsg.setReward(PropertyHelper.parsePropertyToString(p));
        player.sendPacket(Protocol.U_CURIO_GET_RIVER_GIFT, respMsg);

        if(process > 0){
            AutoLogMgr.add(new LogCurioRiverGift(
                    player.getUserId(),
                    process,
                    userCurioData.getRiverProcess(),
                    3,
                    PropertyHelper.parsePropertyToString(p)
            ));
        }
        return 0;
    }

    /**
     * 藏品特权操作
     */
    public int privilegeOpt(int itemId, int opt, int privilegeType) {
        if(!isSystemOpen()){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }
        if(userCurioData == null){
            return GameErrorCode.E_SYSTEM_NO_OPEN;
        }

        CurioItemInfo curioItemInfo = CurioConfigMgr.getConfig().getCurioItemInfo(itemId);
        if(curioItemInfo == null){
            return GameErrorCode.E_CURIO_ITEM_CONFIG_MISSION;
        }

        UserCurioItemData itemData = getUserCurioItemData(itemId);
        if(itemData == null){
            return GameErrorCode.E_CURIO_ITEM_NO_GET;
        }

        if(!curioItemInfo.getPrivilegeDayMap().containsKey(privilegeType)){
            return GameErrorCode.E_REQUEST_ARGUMENT_ERROR;
        }
        CurioPrivilege curioPrivilege = getCurioItemPrivilege(privilegeType, itemData);

        if(curioPrivilege == null){
            return GameErrorCode.E_CURIO_PRIVILEGE_NO_ACTIVE;
        }

        List<UserCurioItemData> changeList = new ArrayList<>();
        if(opt == 0){
            //使用
            if(!curioPrivilege.isUse() && !checkPrivilegeExpire(curioPrivilege)){
                curioPrivilege.setUse(true);
                itemData.setUpdateOption();

                //取消其他同类特权
                for (Map.Entry<Integer, UserCurioItemData> entry : curioItemDataMap.entrySet()) {
                    if(entry.getKey() != itemId){
                        for (CurioPrivilege privilege : entry.getValue().getPrivilegeList()) {
                            if(privilege.getType() == curioPrivilege.getType()){
                                checkPrivilegeExpire(privilege);
                                privilege.setUse(false);
                                entry.getValue().setUpdateOption();
                                changeList.add(entry.getValue());
                            }
                        }
                    }
                }
            }
        }else if(opt == 1){
            //取消
            if(curioPrivilege.isUse()){
                checkPrivilegeExpire(curioPrivilege);
                curioPrivilege.setUse(false);
                itemData.setUpdateOption();
            }
        }

        CurioProto.CurioPrivilegeOperateRespMsg.Builder builder = CurioProto.CurioPrivilegeOperateRespMsg.newBuilder();
        builder.setRet(0);
        builder.setItem(CurioMgr.buildCurioItemTemp(itemData));
        for (UserCurioItemData data : changeList) {
            builder.addChange(CurioMgr.buildCurioItemTemp(data));
        }
        player.sendPacket(Protocol.U_CURIO_PRIVILEGE_OPERATE, builder);
        return 0;
    }

    public CurioPrivilege getCurioItemPrivilege(int privilegeType, UserCurioItemData itemData) {
        CurioPrivilege curioPrivilege = null;
        for (int i = 0; i < itemData.getPrivilegeList().size(); i++) {
            CurioPrivilege privilege = itemData.getPrivilegeList().get(i);
            if(privilege.getType() == privilegeType){
                curioPrivilege = privilege;
            }
        }
        return curioPrivilege;
    }

    private boolean checkPrivilegeExpire(CurioPrivilege curioPrivilege) {
        if(curioPrivilege.getExpire() == -1){
            return false;
        }
        if(curioPrivilege.getExpire() > 0 && curioPrivilege.getExpire() < System.currentTimeMillis() / 1000){
            curioPrivilege.setUse(false);
            return true;
        }
        return false;
    }

    /**
     * 获取散财特权的藏品id
     */
    public int getDisperseGoldPrivilegeItem(){
        int itemId = 0;
        for (Map.Entry<Integer, UserCurioItemData> entry : curioItemDataMap.entrySet()) {
            CurioPrivilege privilege = getCurioItemPrivilege(1, entry.getValue());
            if(privilege != null){
                if(!checkPrivilegeExpire(privilege)){
                    itemId = entry.getKey();
                    break;
                }else {
                    entry.getValue().setUpdateOption();
                }
            }
        }
        return itemId;
    }


    /**
     * 更新勋章
     */
    public void updateBadge() {
        if (SystemOpenMgr.systemOpen(player, eSystemId.BadgeShow.getValue())) {
            if (userCurioData == null) {
                return;
            }
            CurioBadgeInfo badgeInfo = CurioConfigMgr.getConfig().getBadgeInfo(userCurioData.getBadgeLv());
            if (badgeInfo == null) {
                return;
            }
            player.getModule(BadgeModule.class).addBadge(badgeInfo.getId(), eBadgeType.CurioScore.getValue());
        }
    }

    public void addSkill(UserCurioSkillData skillData){
        synchronized (skillDataMap) {
            if (null == getSkill(skillData.getSkill())) {
                skillDataMap.put(skillData.getSkill(), skillData);
                CurioMgr.calSkillAddition(skillData, player);
            }
        }
    }

    public void addUserCurioCountData(int type, long val){
        addUserCurioCountData(type, 0, val);
    }

    public void addUserCurioCountData(int type, int childType, long val) {
        if (!SystemOpenMgr.systemOpen(player, eSystemId.Curio.getValue())) {
            return;
        }
        checkAllCurioItemSpecialSkill();
        //比赚钱计算时的调用保险
        CurioMgr.calAllSkillAddition(player);
    }

    public long getUserCurioCount(int type, int chileType){
        long count = 0;
        Map<Integer, UserCurioCountData> countMap = countDataMap.get(type);
        if(countMap != null){
            for (Map.Entry<Integer, UserCurioCountData> entry : countMap.entrySet()) {
                UserCurioCountData countData = entry.getValue();
                if(countData.getChildType() == chileType){
                    count += countData.getCountValue();
                }
            }
        }
        return count;
    }

    public long getUserCurioCount(int type){
        long count = 0;
        Map<Integer, UserCurioCountData> countMap = countDataMap.get(type);
        if(countMap != null){
            for (Map.Entry<Integer, UserCurioCountData> entry : countMap.entrySet()) {
                UserCurioCountData countData = entry.getValue();
                count += countData.getCountValue();
            }
        }
        return count;
    }

    /**
     * 精进技能上限加成
     *
     */
    @Deprecated
    public int getStageSkillMaxLevelAdd() {
        int addLv = 0;
        if (userCurioData == null) {
            return addLv;
        }
        CurioBadgeInfo badgeInfo = CurioConfigMgr.getConfig().getBadgeInfo(userCurioData.getBadgeLv());
        if (badgeInfo != null) {
            for (int skillId : badgeInfo.getSkillsList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo != null && skillInfo.getType() == eSkillType.FishPondStageSkillMaxLevelAdd.getValue()) {
                    addLv += SkillMgr.getSkillAddition(skillInfo, userCurioData.getBadgeLv());
                }
            }
        }
        return addLv;
    }

    public void resetOneDay(){
        try{
            checkPrivilegeExpire();
        }catch (Exception e){
            CurioMgr.getLogger().error("", e);
        }
    }

    /**
     * 技能上限加成
     *
     */
    public int getSkillMaxLevelAdd() {
        int addLv = 0;
        if (userCurioData == null) {
            return addLv;
        }
        CurioBadgeInfo badgeInfo = CurioConfigMgr.getConfig().getBadgeInfo(userCurioData.getBadgeLv());
        if (badgeInfo != null) {
            for (int skillId : badgeInfo.getSkillsList()) {
                SkillInfo skillInfo = SkillMgr.getSkillInfo(skillId);
                if (skillInfo != null && skillInfo.getType() == eSkillType.SkillMaxLevelAdd.getValue()) {
                    addLv += SkillMgr.getSkillAddition(skillInfo, userCurioData.getBadgeLv());
                }
            }
        }
        return addLv;
    }

    public UserCurioSkillData getSkill(int skillId){
        return skillDataMap.get(skillId);
    }

    public Map<Integer, UserCurioSkillData> getSkillDataMap() {
        return skillDataMap;
    }

    public UserCurioData getUserCurioData() {
        return userCurioData;
    }

    public int getBadgeLv(){
        if(userCurioData == null){
            return  0;
        }
        return userCurioData.getBadgeLv();
    }

    public Map<Integer, UserCurioItemData> getCurioItemDataMap() {
        return curioItemDataMap;
    }

    public UserCurioItemData getUserCurioItemData(int itemId){
        return curioItemDataMap.get(itemId);
    }

    public Map<Integer, Map<Integer, UserCurioCountData>> getCountDataMap() {
        return countDataMap;
    }
}
